import { Active, Key, Deps } from './type'
import { isFunction } from './is'

let active: Active = null

/**
 * 收集副作用
 * @param callback 依赖回调
 */
export const effect = <T extends Function>(callback: T) => {
	active = callback
	active()
	active = null
}

/**
 * 容器
 */
export const vm = new WeakMap()

/**
 * 收集
 * @param target 目标对象
 * @param key 键
 */
export const track = <T extends Object>(
	target: T,
	key: Key
) => {
	if (!isFunction(active)) {
		return
	}

	if (!vm.has(target)) {
		vm.set(target, new Map())
	}

	const deps = vm.get(target) as Deps

	if (!deps.has(key)) {
		deps.set(key, new Set())
	}

	const dep = deps.get(key)!

	dep.add(active)
}

/**
 * 触发
 * @param target 目标对象
 * @param key 键
 */
export const trigger = <T extends Object>(
	target: T,
	key: Key
) => {
	if (!vm.has(target)) {
		return
	}

	const deps = vm.get(target) as Deps

	if (!deps.has(key)) {
		return
	}

	const dep = deps.get(key)!
	dep.forEach(fn => fn())
}
